import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Main {

    private static final Logger log = LoggerFactory.getLogger(Main.class);

    public static void main(String[] args) {
        //我们就可以来看看如何实现一次简单的登录操作了。
        // 这个登录操作我们依然是参考quickstart项目中的类来实现，首先我们要通过shiro.ini创建一个SecurityManager，再将这个SecurityManager设置为单例模式
        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
        SecurityManager securityManager = factory.getInstance();
        SecurityUtils.setSecurityManager(securityManager);

        //如此之后，我们就配置好了一个基本的Shiro环境，注意此时的用户和角色信息我们配置在shiro.ini这个配置文件中，接下来我们就可以获取一个Subject了，这个Subject就是我们当前的用户对象
        Subject currentUser = SecurityUtils.getSubject();

        // 拿到这个用户对象之后，接下来我们可以获取一个session了，这个session和我们web中的HttpSession的操作基本上是一致的，不同的是，这个session不依赖任何容器，可以随时随地获取
        Session session = currentUser.getSession();//获取session
        session.setAttribute("name", "zhangsan");//给session设置属性值
        String name = (String) session.getAttribute("name");//获取session中的属性值
        log.info("name = {}", name);

        // 说了这么多，我们的用户到现在还没有登录呢，Subject中有一个isAuthenticated方法用来判断当前用户是否已经登录，如果isAuthenticated方法返回一个false，则表示当前用户未登录，那我们就可以执行登陆
        // 首先构造UsernamePasswordToken，两个参数就是我们的用户名和密码，然后调用Subject中的login方法执行登录，当用户名输错，密码输错、或者账户锁定等问题出现时，系统会通过抛异常告知调用者这些问题
        if (!currentUser.isAuthenticated()) {
            UsernamePasswordToken token = new UsernamePasswordToken("sang", "123");
//            UsernamePasswordToken token = new UsernamePasswordToken("十画生", "123");
            try {
                currentUser.login(token);
            } catch (UnknownAccountException uae) {
                log.error("用户名不正确 {}", token.getPrincipal());
                return;
            } catch (IncorrectCredentialsException ice) {
                log.error("密码不正确 {}",token.getPrincipal());
                return;
            } catch (LockedAccountException lae) {
                log.error("用户名为 {} 的账号被锁定",token.getPrincipal());
                return;
            }
            // ... catch more exceptions here (maybe custom ones specific to your application?
            catch (AuthenticationException ae) {
                //unexpected condition?  error?
                log.error("账号 {} 认证失败",token.getPrincipal());
                return;
            }
        }

        // 当登录成功之后，我们可以通过如下方式获取当前登陆用户的用户名
        if (currentUser.isAuthenticated()) {
            log.info("用户 [{}] 登录成功", currentUser.getPrincipal());
        }

        // 我们也可以通过调用Subject中的hasRole和isPermitted方法来判断当前用户是否具备某种角色或者某种权限
        String roleIdentifier = "普通用户";
        if (currentUser.hasRole(roleIdentifier)) {
            log.info("具有 [{}] 角色",roleIdentifier);
        } else {
            log.info("没有 [{}] 角色",roleIdentifier);
        }
        String permission = "book:add";
        if (currentUser.isPermitted(permission)) {
            log.info("具有 [{}] 权限",permission);
        } else {
            log.info("没有 [{}] 权限",permission);
        }

        currentUser.logout();
    }

}
